#pragma  once

#ifndef _XBOX
#include <Windows.h>
#endif

#ifdef WIN32
#include <dinput.h>
#endif

#include "3rdparty/Leo/LeoAPI.h"

#if 1
#ifndef WIN32
#define DIK_UP 0
#define DIK_DOWN 0
#define DIK_LEFT 0
#define DIK_RIGHT 0
#define DIK_0 0
#define DIK_1 0
#define DIK_2 0
#define DIK_3 0
#define DIK_RETURN 0
#define DIK_BACK 0
#define DIK_PAUSE 0
#define DIK_SPACE 0
#define DIK_LSHIFT 0
#define DIK_LCONTROL 0
#define DIK_I 0
#endif

#ifdef WIN32
struct IDirectInputDevice8;
struct IDirectInput8;
#endif

struct keyboard_t
{
	keyboard_t();

	bool key_pressed(int index) const;
	bool key_released(int index) const;
	bool key_down(int index) const;
	bool IsKeyDown(int index) const{return key_down(index);}
	void update();

#ifdef WIN32
	unsigned char keyboard_state[256];
	unsigned char prev_keyboard_state[256];
	IDirectInputDevice8 *device;
#endif
};

struct mouse_t
{
	mouse_t();
#ifdef WIN32
	DIMOUSESTATE2	mouse_state;
	DIMOUSESTATE2	prev_mouse_state;
	IDirectInputDevice8 *device;
#endif

	int get_mouse_x()
	{
		return mouse_state.lX;
	}
	int get_mouse_y()
	{
		return mouse_state.lY;
	}
	int get_mouse_z()
	{
		return mouse_state.lZ;
	}

	float3 get_mouse_pos()
	{
		return float3((float)mouse_state.lX,(float)mouse_state.lY,(float)mouse_state.lZ);
	}
	bool button_down(int i_Btn)
	{
		ASSERT (i_Btn>=0 && i_Btn<8);
		return (mouse_state.rgbButtons[i_Btn])!=0;
	}

	bool button_pressed(int i_Btn)
	{
		ASSERT (i_Btn>=0 && i_Btn<8);
		return (mouse_state.rgbButtons[i_Btn] && !prev_mouse_state.rgbButtons[i_Btn])!=0;
	}

	bool button_released(int i_Btn)
	{
		ASSERT (i_Btn>=0 && i_Btn<8);
		return (!mouse_state.rgbButtons[i_Btn] & prev_mouse_state.rgbButtons[i_Btn])!=0;
	}

	void hide();
	void show();


	void update();

	bool shown;
};

struct leodevice_t
{
	leodevice_t();
	~leodevice_t();

	void update();

	float3 get_bird_pos() const;
	float3 get_bird_rot() const;
	float4x4 get_bird_mtx() const;

	bool small_button_down() const;
	bool small_button_pressed() const;
	bool small_button_released() const;
	bool big_button_down() const;

	void set_vibration(float val);

	float3 birdpos;
	float3 birdrot;

	static bool device_present;
};

//gamepad defines
#define BUTTON_DPAD_UP 0
#define BUTTON_DPAD_DOWN 1
#define BUTTON_DPAD_LEFT 2
#define BUTTON_DPAD_RIGHT 3
#define BUTTON_START 4
#define BUTTON_BACK 5
#define BUTTON_LEFT_STICK 6
#define BUTTON_RIGHT_STICK 7
#define BUTTON_LEFT_BUMPER 8
#define BUTTON_RIGHT_BUMPER 9

#define BUTTON_A 12
#define BUTTON_FIRE BUTTON_A
#define BUTTON_B 13
#define BUTTON_X 14
#define BUTTON_Y 15
#define BUTTON_LEFT_TRIGGER 10
#define BUTTON_RIGHT_TRIGGER 11


#define AXIS_LEFTSTICK_X 0
#define AXIS_LEFTSTICK_Y 1
#define AXIS_RIGHTSTICK_X 2
#define AXIS_RIGHTSTICK_Y 3
#define AXIS_LEFTTRIGGER 4
#define AXIS_RIGHTTRIGGER 5

#define INPUT_NUMAXIS 6

#define INPUT_NUMMAXGAMEPADS 4

struct gamepad_t
{
	bool button_pressed(int index) const;
	bool button_released(int index) const;
	bool axis_pressed_up(int index) const;
	bool axis_pressed_down(int index) const;
	float button(int index) const;
	float Button(int index) const{return button(index);}
	float axis(int index) const;
	float prev_axis(int index) const;
	bool ButtonReleased(int index) const{return button_released(index);}
	bool ButtonPressed(int index) const{return button_pressed(index);}
//	XINPUT_STATE state,prev_state;
	int pad_index;
	void update();
	void set_vibration(float v);
	void set_vibration(float v_l, float v_r);
	void init(int idx);
	void reset();

	bool is_idle() const;

	struct state_t
	{
		bool connected;
		uint16 button_state;
		int8 axis_state[INPUT_NUMAXIS];

		state_t(){}
	} state,prev_state;
	
};

struct inputsystem_t
{
	static void init(HWND hwnd);
	static void exit();
	inputsystem_t(HWND hwnd);
	~inputsystem_t();
	void reset();
	void update();
	keyboard_t* get_keyboard() { return &keyboard; };
	gamepad_t* get_gamepad(int index) { return gamepad+index; };
	int get_number_of_gamepads() const { return INPUT_NUMMAXGAMEPADS; };
	void enable_mouse_and_keyboard(bool enable);

	bool mouse_and_keyboard_enabled;

	keyboard_t keyboard;
	mouse_t mouse;
	gamepad_t gamepad[INPUT_NUMMAXGAMEPADS];
	leodevice_t leodevice;

	HWND hwnd;

#ifdef LEO_DESIGNER
	gamepad_t editor_gamepad;
#endif

#ifdef WIN32
	IDirectInput8 *hw_input;
#endif
};

extern inputsystem_t* INPSYS;
#endif

